//
//  File.cpp
//  SOC
//
//  Created by Benson Tran on 1/7/13.
//  Copyright (c) 2013 Benson Tran. All rights reserved.
//  


#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <vector>
#include "core.h"
using namespace std;


void core::init(int p, int W, int T, int w, int t) {
    
    this->p = p; this->W = W; this->T = T; this->t = t; this->w = w;
    
}

 int core::wmaxtest(core Array[], int Wmax, int N){
    
    for(int i = 0; i < N; i++){
        if(Array[i].W + Array[i].w > Wmax){
            cout << "Test 1: Failed" << endl;
            return -1;
        }
        
    }
     cout << "Test 1: Passed" << endl;
     return 1;
    

}

int core::overlap(core Array[], int Wmax, int N){
    
    int corecount = 0;



    
    while(corecount < (N-1) ){
        for(int i = 0; corecount < N - 1 - i; i++){
            //cout << Array[N-1-i].w << endl;
            //cout << corecount << endl;
            if(Array[corecount].w >= Array[N - 1 - i].w &&
               (Array[corecount].t + Array[corecount].T) > Array[N - 1 - i].t &&
               (Array[corecount].t + Array[corecount].T) <= (Array[N - 1 - i].t + Array[N - 1 - i].T) &&
               Array[corecount].w < (Array[N - 1 - i].w + Array[N - 1 - i].W)){
                
            cout << "Test 2: Failed" << endl;
            return -1;
                

            }
            
            else if(Array[corecount].w >= Array[N - 1 - i].w &&
                    Array[corecount].t >= Array[N - 1 - i].t &&
                    Array[corecount].t < (Array[N - 1 - i].t + Array[N - 1 - i].T) &&
                    Array[corecount].w < (Array[N - 1 - i].w + Array[N - 1 - i].W)){
                
                cout << "Test 2: Failed" << endl;
                return -1;

            }
            
            else if((Array[corecount].w + Array[corecount].W) > Array[N - 1 - i].w &&
               (Array[corecount].t + Array[corecount].T) > Array[N - 1 - i].t &&
               (Array[corecount].t + Array[corecount].T) <= (Array[N - 1 - i].t + Array[N - 1 - i].T) &&
               (Array[corecount].w + Array[corecount].W) <= (Array[N - 1 - i].w + Array[N - 1 - i].W)){
                
                cout << "Test 2: Failed" << endl;
                return -1;
                
                
            }
            
            else if((Array[corecount].w + Array[corecount].W) > Array[N - 1 - i].w &&
                    Array[corecount].t >= Array[N - 1 - i].t &&
                    Array[corecount].t < (Array[N - 1 - i].t + Array[N - 1 - i].T) &&
                    (Array[corecount].w + Array[corecount].W) <= (Array[N - 1 - i].w + Array[N - 1 - i].W)){
                
                cout << "Test 2: Failed" << endl;
                return -1;
                
            }
            
        
        }
        corecount++;
    }
    
    cout << "Test 2: Passed" << endl;
    return 1;
    
}

int core::makespan(core Array[], int N){
    
    int holder = 0;
    for(int i = 0; i < N; i++){
        if(Array[i].t + Array[i].T > holder){
            
            holder = Array[i].t + Array[i].T;
        }
    }
    
    cout << "Makespan: " << holder << endl;
    return holder;
}

int core::powercheck(core Array[], int Pmax, int N, int * powerholder){
    *powerholder = 0;
    
    for(int i = 0; i < N; i++){
        
        int time = Array[i].t;
        int power = Array[i].p;

        for(int j = 0; j < N; j++) {
            if(j != i){
                if(time < (Array[j].t + Array[j].T) && time >= Array[j].t){
                    
                    power += Array[j].p;
                    
                }
            }
            
        }
        if(*powerholder < power){
            
            *powerholder = power;
            
        }
        if(power > Pmax){
            
            cout << "Power constraint not met at time " << Array[i].t << " with power " << power << "." << endl;
            
            return -1;
        }
    
        if(Pmax > *powerholder){
            *powerholder = Pmax;
        }
    }
    
    cout << "Power constraint met." << endl;
    return 1;
}

void core::coloring(core Array[], string Colors[], int N){
    
    for(int i = 0; i < N; i++){
        
        Array[i].color = Colors[i % sizeof(Colors)];
        
    }
    
}

void core::latex(core Array[], int N, int Wmax, int Makespan){

    
    ofstream myLatex;
    
    myLatex.open ("cores.tex");
    
    myLatex << "\\documentclass{report}\n";
    
    myLatex << "\\usepackage[usenames,dvipsnames]{xcolor}\n";
    
    myLatex << "\\usepackage{tikz}\n";
    
    myLatex << "\\begin{document}\n";
    
    myLatex << "\\resizebox{\\textwidth}{!}{\n";
    
    myLatex << "\\begin{tikzpicture}\n";
    
    for(int i = 0; i < N; i++){
        
        myLatex << "\\filldraw[draw=black,fill=" << Array[i].color << "]" "("
        << Array[i].t << "," << -(Array[i].w + Array[i].W)
        << ") rectangle (" << (Array[i].t + Array[i].T) << "," << -(Array[i].w) << ");\n";
        
    }
    
 
    myLatex << "\\end{tikzpicture}\n";
    
    myLatex << "}\n";
    
    myLatex << "\\end{document}\n";
    
    myLatex.close();
}

void core::plot(core Array[], int N, int hold, int Pmax){
    
    int * timeArray;
    timeArray = new int[2*N];
    int timecounter = 0;;
    int temp;
    
    for(int i = 0; i < N; i++){ // Create an array with all the beginning/endpoints of cores
        
        timeArray[timecounter] = Array[i].t;
        timeArray[timecounter + 1] = Array[i].t + Array[i].T;
        timecounter = timecounter + 2;
        
    }
    
    for(int i = (2*N - 1); i > 0; i--) //sort timearray, so edges are in ascending order.
    {
        for(int j = 1; j <= i; j++)
        {
            if(timeArray[j-1] > timeArray[j])
            {
                temp = timeArray[j-1];
                timeArray[j-1] = timeArray[j];
                timeArray[j] = temp;
                
            }
        }
    }

    
    ofstream myMatlab;
    
    myMatlab.open ("graph.m");
    
    myMatlab << "figure(1);\n";
    
    myMatlab << "time = [";
    

    for(int i = 0; i < 2*N; i++){
        myMatlab << timeArray[i];
        myMatlab << " ";
    }
        
 
    
    myMatlab << "];\n";
    
    myMatlab << "power = [";
    
    for(int i = 0; i < 2*N; i++){
        
        int power = 0;
        
        for(int j = 0; j < N; j++){
            if(timeArray[i] < (Array[j].t + Array[j].T) && timeArray[i] >= Array[j].t){

                    power += Array[j].p;

                }
            }
        
         myMatlab << power << " ";       

        }
    
    
    myMatlab << "];\n";
    
    int maxtime = timeArray[2*N-1]; //used for axis sizing
    
    myMatlab << "stairs(time, power, 'k-');\n";
    myMatlab << "line('XData', [0, "<<  maxtime + maxtime/9 << "], 'YData', [" << Pmax << ", " << Pmax << "], 'LineStyle', '--', 'LineWidth', 2, 'Color','b');\n";
    myMatlab << "axis([0 " << maxtime + maxtime/9 << " 0 " << hold + hold/9 << "]);\n";
    myMatlab << "legend('P(t)', 'Pmax');\n";
    myMatlab << "xlabel('Time (seconds)');\n";
    myMatlab << "ylabel('Power Consumed (watts)');\n";
    myMatlab << "title('Power Consumed vs. Time');\n";
    
    myMatlab.close();
    
    
}